# -*- coding:utf-8 -*-
# @author: LY
# @time:2022/8/22 0022:11:41
import pdb
import threading
import warnings
warnings.filterwarnings("ignore")
import re, requests, json, time, copy, random

from urllib.parse import quote, unquote

class parse_addr():
    def __init__(self):
        pass

    def parse_mode(self, urls, method="post", header=None, datas=None):
        tries = 0
        while tries < 5:
            try:
                if method.lower() == "post":
                    if datas:
                        if header:
                            res = requests.post(url=urls, headers=header, data=datas, timeout=5, verify=False)
                        else:
                            res = requests.post(url=urls, data=datas, timeout=5, verify=False)
                    else:
                        if header:
                            res = requests.post(url=urls, headers=header, timeout=5, verify=False)
                        else:
                            res = requests.post(url=urls, timeout=5, verify=False)
                else:
                    if header:
                        if datas:
                            res = requests.get(url=urls, headers=header, params=datas, timeout=5, verify=False)
                        else:
                            res = requests.get(url=urls, headers=header, timeout=5, verify=False)
                    else:
                        if datas:
                            res = requests.get(url=urls, params=datas, timeout=5, verify=False)
                        else:
                            res = requests.get(url=urls, timeout=5, verify=False)
                if not res or res.status_code != 200:
                    raise
                return res
            except requests.exceptions.ReadTimeout:
                return None
            except:
                tries += 1
                time.sleep(1)

    def format_data(self, response):
        if not response:
            return None
        if "权限" in response.text or "封禁" in response.text or "余额" in response.text or "限制" in response.text or "访问已超出日访问量" in response.text or "IP访问超限" in response.text or "配额" in response.text or "上限" in response.text:
            return None
        return True

    def shunfeng_parse(self, header, addr_str, province, city):
        urls = 'https://www.sf-express.com/sf-service-owf-web/service/order/batch/orderAddressSplit?lang=sc&region=cn&translate=sc'
        header = {
            "Accept": "application/json, text/plain, */*",
            "Content-Type": "application/json;charset=UTF-8",
            "Host": "www.sf-express.com",
            "Origin": "https://www.sf-express.com",
            "Referer": "https://www.sf-express.com/we/ow/chn/sc/ship/home",
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36",
        }
        datas = {"address": addr_str}
        result = self.parse_mode(urls, method="post", header=header, datas=json.dumps(datas))
        res = self.format_data(result)
        if not res:
            return {"tries": 1}
        res_dict = result.json()
        if not res_dict.get("success"):
            return {"tries": 1}
        if res_dict.get("result"):
            try:
                if res_dict.get("result")[0]["originDestRegions"]:
                    pass
            except:
                return {"tries": 1}
            temporary_mode = res_dict.get("result")[0]["originDestRegions"]
            temporary_dict = {}
            city_list = ["province", "city", "district"]
            for index_, value in enumerate(temporary_mode):
                temporary_dict[city_list[index_]] = temporary_mode[index_]["name"]
            return temporary_dict
        else:
            return {"tries": 1}

    def yunda_parse(self, header, addr_str, province, city):
        datas = {
            "appid": "ydmb",
            "isSave": "N",
            "openid": "undefined",
            "receiverInfo": addr_str,
            "req_time": int(time.time() * 1000) - 3,
            "version": "V1.0",
        }
        urls = 'http://membernew.yundasys.com:15116/ydaddress/AddrAnalysis'
        header = {
            "Accept": "application/json, text/javascript, */*; q=0.01",
            "Content-Type": "application/json;charset=UTF-8",
            "Host": "membernew.yundasys.com:15116",
            "Origin": "http://membernew.yundasys.com:15116",
            "Referer": "http://membernew.yundasys.com:15116/member.website/hywz/view/shipping.html",
            "X-Requested-With": "XMLHttpRequest",
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36",
        }
        result = self.parse_mode(urls, method="post", header=header, datas=json.dumps(datas))
        res = self.format_data(result)
        if not res:
            return {"tries": 1}
        res_dict = result.json()
        if res_dict.get("message") not in ["请求成功", "success", "成功"]:
            return {"tries": 1}
        if res_dict.get("data"):
            if res_dict["data"].get("allAddrList"):
                temporary_mode = res_dict["data"]["allAddrList"]
                temporary_dict = {}
                temporary_dict["province"] = temporary_mode[0]["receiverProvince"]
                temporary_dict["city"] = temporary_mode[0].get("receiverCity")
                temporary_dict["district"] = temporary_mode[0].get("receiverArea")
                return temporary_dict
            else:
                return {"tries": 1}
        else:
            return {"tries": 1}

    def kuaidi100_parse(self, header, addr_str, province, city):
        datas = {"method": "infosplit", "content": addr_str}
        urls = 'https://www.kuaidi100.com/market/open/sent.do'
        header = {
            "Accept": "application/json, text/javascript, */*; q=0.01",
            "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
            "Host": "www.kuaidi100.com",
            "Origin": "https://www.kuaidi100.com",
            "Referer": "https://www.kuaidi100.com/courier/",
            "X-Requested-With": "XMLHttpRequest",
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36",
        }
        result = self.parse_mode(urls, method="post", header=header, datas=datas)
        res = self.format_data(result)
        if not res:
            return {"tries": 1}
        res_dict = result.json()
        if res_dict.get("message") not in ["请求成功", "success", "成功"]:
            return {"tries": 1}
        if res_dict.get("data"):
            if res_dict["data"][0].get("xzq"):
                temporary_mode = res_dict["data"][0]["xzq"]
                temporary_dict = {}
                temporary_dict["province"] = temporary_mode["indexFullName"]["firstName"]
                temporary_dict["city"] = temporary_mode["indexFullName"].get("secondName", "")
                temporary_dict["district"] = temporary_mode["indexFullName"].get("thirdName", "")
                return temporary_dict
            else:
                return {"tries": 1}
        else:
            return {"tries": 1}

    def tianditu_qg(self, header, addr_str, province, city):
        urls = 'http://api.tianditu.gov.cn/v2/search?postStr={"keyWord":"%s","level":18,"resultType":"1", "mapBound":"116.02524,39.83833,116.65592,39.99185","queryType":1,"start":0,"count":1, "show":2}&type=query&tk=%s' % (addr_str, "d00b1a753bcbc011d78c81b8d6af371a")
        result = self.parse_mode(urls, method="get")
        res = self.format_data(result)
        if not res:
            return {"tries": 1}
        res_dict = result.json()
        if res_dict.get("resultType") != 1:
            return {"tries": 1}
        if res_dict.get("pois"):
            temporary_dict = {}
            temporary_dict["province"] = res_dict["pois"][0]["province"]
            temporary_dict["city"] = res_dict["pois"][0].get("city", "")
            temporary_dict["district"] = res_dict["pois"][0].get("county", "")
            return temporary_dict
        else:
            return {"tries": 1}
    
    def tentxunqq_map(self, header, addr_str, province, city):
        tengxun_key_list = [
            "UF4BZ-NURY6-NZGSA-MBFOV-MMYW6-JRBFE", "FAGBZ-ABXW2-TY4U5-CFL7E-6QJZZ-7SFA5",
            "TCEBZ-AHUKV-BPYPX-U6Z7T-T35LK-5YBBF", "D4GBZ-TRBCP-MIFD7-VJYQE-RS3C3-3JBRE",
            "46RBZ-63DWD-YVK45-PUTWA-HVL4T-OIBOQ", "WYMBZ-NR33U-QI3VM-2IQX6-TFECO-F5BFT",
            "HZXBZ-R4YWD-UUF4P-HM2FE-NQS4F-2WFIH", "KTGBZ-7K5R4-VJDUQ-DWIOQ-P43AH-HXFBR",
            "ZHWBZ-X3PHO-X3SW4-SOCQ3-VWPLQ-LNFX6", "JIIBZ-ZWR3X-OH44W-Z4HHB-A4QWF-HHF5Y",
            "VYHBZ-4VZWD-OOS4Y-HELN5-RQWBS-G7BFH", "GN2BZ-GIXKQ-OHT5F-GMUPA-VSAMZ-TZBK2",
            "U36BZ-ESOKQ-HPX5G-GOZ2J-YSVM3-GFF4D", "LEJBZ-4M3CW-CU2R4-OR6QQ-WUCO2-LJBXH",
            "4B7BZ-SJGKW-5DGRZ-RAPCY-OEHGE-PWBGF", "KNGBZ-4B26O-LTFW2-SWZIR-EXYVK-HOB7H",
            "LB2BZ-RTH6U-RKKV7-27QPM-B6HDE-MRF5F", "SBSBZ-XPBLJ-WEXFU-KD3NR-JUWPT-RNFOJ",
            "YCJBZ-G2L6O-LT7WR-SXSLA-LVXVE-APF6X", "CQGBZ-DH5LJ-DEOFI-K54CY-XSUPJ-OQBJH",
            "74ABZ-6RME6-U5VSU-EYE46-ML4ZK-D2BOY", "Y4ABZ-4WFLU-6SAV5-B3N7Q-S3JUE-SJF5V",
            "HW4BZ-JK3LW-QBJRT-OCHHM-DSXOF-VCBP2", "5EYBZ-56LLJ-URPFO-KSF25-SOVHQ-H2F34",
            "VP4BZ-DLLEQ-PQX5Z-GZJ52-SOJM5-WUBTN"
        ]
        tengxun_key_list_copy = copy.deepcopy(tengxun_key_list)
        while True:
            key = random.choice(tengxun_key_list_copy)
            try:
                header = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36"}
                if not tengxun_key_list_copy:
                    return {"tries": 1}
                urls = "https://apis.map.qq.com/jsapi?qt=geoc&addr={}&key={}&output=jsonp&pf=jsapi&ref=jsapi&cb=qq.maps._svcb3.geocoder0".format(quote(addr_str, errors="ignore"), key)
                result = self.parse_mode(urls, header=header, method="get")
                res = self.format_data(result)
                if not res:
                    return {"tries": 1}
                if "no result" in result.text:
                    return {"tries": 1}
                response = result.text.replace('qq.maps._svcb3.geocoder0&&qq.maps._svcb3.geocoder0', "")
                response = response.replace('qq.maps._svcb3.geocoder0', "").strip('(').strip(')')
                res_dict = json.loads(response)
                if res_dict.get("status", '') == 140:
                    raise
                if res_dict.get("resultType") != 1:
                    return {"tries": 1}
                if res_dict.get("detail"):
                    temporary_dict = {}
                    temporary_dict["province"] = res_dict["detail"]["province"]
                    temporary_dict["city"] = res_dict["detail"].get("city", "")
                    temporary_dict["district"] = res_dict["detail"].get("district", "")
                    return temporary_dict
                else:
                    return {"tries": 1}
            except:
                time.sleep(1)
                tengxun_key_list_copy.remove(key)

    def gaode_parse(self, header, addr_str, province, city):
        key_list = [
            '7515a833ef27ba7d8c5efcd3f9fc69a8', '9decc56703e0ff54bf3900b1366964b2',
            '424af97f0adbb42d291f7a4ec0a0dbac', '009b3e58ad5ba996be37cd80d9c267ae',
            'ee4c9f14e60cde822ecdea51e70fc04b', '0ab59976e83005aac9f790bb9e364b0f',
            '86e9a4b34c3d907cdd71f5f3f291fda5', '86e9a4b34c3d907cdd71f5f3f291fda5',
            '86e9a4b34c3d907cdd71f5f3f291fda5', 'd4b90a7f0181a20d25f6d450f6452184',
            'd4b90a7f0181a20d25f6d450f6452184', 'd4b90a7f0181a20d25f6d450f6452184',
            'eaed66c971e6264cedfdc0634f890373'
        ]
        while True:
            if not key_list:
                return {"tries": 1}
            key = random.choice(key_list)
            urls = 'https://restapi.amap.com/v5/geocode/geo?address={}&output=XML&key={}&output=json'.format(addr_str, key)
            result = self.parse_mode(urls, method="get")
            res = self.format_data(result)
            if not res:
                key_list.remove(key)
                time.sleep(1)
                continue
            res_dict = result.json()
            if res_dict['info'] == 'OK':
                if res_dict.get("pois"):
                    temporary_dict = {}
                    temporary_dict["province"] = res_dict["pois"][0]["pname"]
                    temporary_dict["city"] = res_dict["pois"][0]["cityname"]
                    temporary_dict["district"] = res_dict["pois"][0]["adname"]
                    return temporary_dict
                elif res_dict["geocodes"]:
                    temporary_dict = {}
                    temporary_dict["province"] = res_dict["geocodes"][0]["province"]
                    temporary_dict["city"] = res_dict["geocodes"][0]["city"]
                    temporary_dict["district"] = res_dict["geocodes"][0]["district"]
                    return temporary_dict
                else:
                    return {"tries": 1}
            else:
                return {"tries": 1}

    def baidu_parse(self, header, addr_str, province, city):
        header = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36"}
        urls = "https://api.map.baidu.com/?callback=window.jsonpcb.jsonpcb4&qt=s&c=131&wd={}&rn=10&ie=utf-8&oue=1&fromproduct=jsapi&res=api".format(quote(addr_str))
        result = self.parse_mode(urls, header=header, method="get")
        res = self.format_data(result)
        if not res:
            return {"tries": 1}
        addr_con = re.search('("content":.*),"current_city":', result.text)
        addr_con_new = json.loads("{" + addr_con.groups()[0] + "}")
        add_dict = addr_con_new["content"][0]["api_admin_info"]
        if add_dict:
            temporary_dict = {}
            temporary_dict["province"] = add_dict.get("prov_name") if add_dict.get("prov_name") else add_dict.get("city_name", "")
            temporary_dict["city"] = add_dict.get("city_name", "")
            temporary_dict["district"] = add_dict.get("area_name", "")
            return temporary_dict
        else:
            return {"tries": 1}

    def check_item(self, addr_dict, province, city):
        if not addr_dict:
            return None
        if addr_dict.get("tries"):
            return None
        if not addr_dict.get("city"):
            return None
        if not addr_dict.get("province"):
            return None
        if province:
            if province != addr_dict["province"]:
                return None
        if city:
            if city != addr_dict["city"]:
                return None
        return addr_dict

    def run(self, addr_str, province=None, city=None):
        header = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36"}
        addr_str = re.sub(r'[a-zA-Z0-9）（]{4,}|、', '', addr_str)
        province = province
        city = city
        tries_num = 0
        best_dict = {}
        addr_dict = {}
        try:
            addr_dict = self.tianditu_qg(header, addr_str, province, city)
        except:
            addr_dict = None
        addr_dict = self.check_item(addr_dict, province, city)
        if type(addr_dict) == dict:
            addr_dict["from"] = "天地图"
            addr_dict["addr_str"] = addr_str
            if not addr_dict.get("tries"):
                if addr_dict.get("district"):
                    return addr_dict
                best_dict.update(addr_dict)
        if not addr_dict or not best_dict.get("district"):
            try:
                addr_dict = self.tentxunqq_map(header, addr_str, province, city)
            except:
                addr_dict = None
            addr_dict = self.check_item(addr_dict, province, city)
            if type(addr_dict) == dict:
                addr_dict["from"] = "腾讯api"
                addr_dict["addr_str"] = addr_str
                if not addr_dict.get("tries"):
                    if addr_dict.get("district"):
                        return addr_dict
                    if not best_dict.get("city"):
                        best_dict.update(addr_dict)
        if not addr_dict or not best_dict.get("district"):
            try:
                addr_dict = self.shunfeng_parse(header, addr_str, province, city)
            except:
                addr_dict = None
            addr_dict = self.check_item(addr_dict, province, city)
            if type(addr_dict) == dict:
                addr_dict["from"] = "顺丰api"
                addr_dict["addr_str"] = addr_str
                if not addr_dict.get("tries"):
                    if addr_dict.get("district"):
                        return addr_dict
                    if not best_dict.get("city"):
                        best_dict.update(addr_dict)
        # if not addr_dict or not best_dict.get("district"):
        #     try:
        #         addr_dict = self.yunda_parse(header, addr_str, province, city)
        #     except:
        #         addr_dict = None
        #     addr_dict = self.check_item(addr_dict, province, city)
        #     if type(addr_dict) == dict:
        #         addr_dict["from"] = "韵达api"
        #         addr_dict["addr_str"] = addr_str
        #         if addr_dict.get("district"):
        #             return addr_dict
        #         if not addr_dict.get("tries"):
        #             if not best_dict.get("city"):
        #                 best_dict.update(addr_dict)
        # if not addr_dict or not best_dict.get("district"):
        #     try:
        #         addr_dict = self.kuaidi100_parse(header, addr_str, province, city)
        #     except:
        #         addr_dict = None
        #     # print("快递100", addr_dict)
        #     addr_dict = self.check_item(addr_dict)
        #     if type(addr_dict) == dict:
        #         if addr_dict.get("district"):
        #             return addr_dict
        #         if not addr_dict.get("tries"):
        #             if not best_dict.get("city"):
        #                 best_dict.update(addr_dict)
        if not addr_dict or not best_dict.get("city"):
            try:
                addr_dict = self.baidu_parse(header, addr_str, province, city)
            except:
                addr_dict = None
            addr_dict = self.check_item(addr_dict, province, city)
            if type(addr_dict) == dict:
                addr_dict["from"] = "百度api"
                addr_dict["addr_str"] = addr_str
                if addr_dict.get("district"):
                    return addr_dict
                if not addr_dict.get("tries"):
                    if not best_dict.get("city"):
                        best_dict.update(addr_dict)
        if not addr_dict or not best_dict.get("city"):
            try:
                addr_dict = self.gaode_parse(header, addr_str, province, city)
            except:
                addr_dict = None
            addr_dict = self.check_item(addr_dict, province, city)
            if type(addr_dict) == dict:
                addr_dict["from"] = "高德api"
                addr_dict["addr_str"] = addr_str
                if addr_dict.get("district"):
                    return addr_dict
                if not addr_dict.get("tries"):
                    if not best_dict.get("city"):
                        best_dict.update(addr_dict)
        if best_dict.get("city"):
            return best_dict
        if not addr_dict:
            return {"tries": 1}
        return addr_dict


if __name__ == '__main__':
    pass
    # addr_ = "上海市临港新片区04PD-0303单元H07-03地块租赁住宅项目（除桩基部分）——补充招标文件公告临港新片区04PD-0303单元H07-03地块租赁住宅项目（除桩基部分）——第一次补充招标文件公告"
    # addr_ = "河南省华北水利水电大学（龙子湖校区）增容供配电项目[变更公告]"       #2f9b7c0beeca97b32f8612b8b1bed45d
    # addr_ = '河北省刑事技术消耗'
    # addr_ = '河北省G1306242101432001阜平县椿天小镇建设项目中标候选人公示'
    # addr_ = "山东省【青岛】青岛海洋科学与技术国家实验室东区二期海洋能源开发利用平台项目室外工程招标公告青岛海洋科学与技术国家实验室东区二期海洋能源开发利用平台项目室外工程招标公告"
    addr_ = "宜阳县"
    # while True:
    print(parse_addr().run("洛阳市瀍河回族区启明中学宿舍楼、综合楼提升改造工程招标公告", ""))
    #     time.sleep(0.1)
    # print(parse_addr().tentxunqq_map("", addr_, "", ""))